package utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysQuestion;
import com.ruoyi.common.core.domain.entity.SysQuestionRecord;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.report.ReportUtil;
import com.ruoyi.system.domain.SysDiagnosisDetail;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class ReportCreater {

    private static final long serialVersionUID = 1L;

    private String outPut= RuoYiConfig.getReportProfile();
    private String localPath = RuoYiConfig.getProfile();

    private String reporttmpl="";

    private XWPFDocument doc;

    /** 企业编码 */
    private Long companyId;

    /** 问卷编码 */
    private Long naireId;

    private String companyName="";

    private List<TreeSelect> domainTrees;

    private HashMap<Long,Double> getScores_l3;

    private  HashMap<Long, HashMap<String, String>> labels;

    private  HashMap<String, String> textMap = new HashMap<>();

   private List<SysDiagnosisDetail> sysDiagnosisDetails;

   private List<SysQuestion> sysQuestions;

   private List<SysQuestionRecord> records;

   private  HashMap<Long,HashMap<Integer, List<SysQuestion>>> questions=new HashMap<>();

   private  HashMap<Long,SysDiagnosisDetail> diagnosisDetailMap=new HashMap<>();

    private  HashMap<Long,SysQuestionRecord> recordMap=new HashMap<>();

    public ReportCreater(Long companyId,String companyName, Long naireId, List<TreeSelect> domainTrees,String reporttmpl,List<SysDiagnosisDetail> sysDiagnosisDetails,List<SysQuestion> sysQuestions,List<SysQuestionRecord> records) {
        this.companyId = companyId;
        this.naireId = naireId;
        this.domainTrees = domainTrees;
        this.reporttmpl=reporttmpl;
        this.companyName=companyName;
        this.sysDiagnosisDetails=sysDiagnosisDetails;
        this.sysQuestions=sysQuestions;
        this.records=records;
        this.doc = ReportUtil.openTmpl(localPath+reporttmpl);
    }


    public String generReport(){
        initQuestions();
        initDiagnosisDetailMap();
        initRecordMap();
        HashMap<Long,Double>getScores_l3=getScores_l3(diagnosisDetailMap,questions);
        HashMap<Long, HashMap<String, String>> labels = getLabel_l3(diagnosisDetailMap, questions);
        HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> qlabels = getProblemLabelsForReport(domainTrees, getScores_l3, labels);
        HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> slabels = getSuggestionLabelsForReport(domainTrees, getScores_l3, labels);

        textMap.put("${company}", getCompanyName());

        try {
            List<String> imageStrs=ReportUtil.getImageString(doc);
            HashMap<String , HashMap<String,Double>> imageData=new HashMap<>();
            for(String imageStr:imageStrs){
                HashMap<String,Double>score=getScoreForRaddar(imageStr,domainTrees,getScores_l3);
                for (String key:score.keySet()){
                    String  str = String.format("%.1f",score.get(key) );
                    double four = Double.parseDouble(str);
                    score.put(key, four);
                }
                imageData.put(imageStr,score);
            }

            doc = ReportUtil.insertText(doc, textMap);
            doc = ReportUtil.insertImage(doc, imageData);
            doc = ReportUtil.insertProblem2(doc, qlabels);
            doc=ReportUtil.insertSuggestions(doc,slabels);

        } catch (Exception e) {
            e.printStackTrace();
        }
        outPut+=getCompanyId()+"/"+getNaireId()+"/"+getCompanyName()+"普查报告-"+ DateUtils.dateTimeNow()+".docx";
        ReportUtil.generateDocx(doc,outPut);
        return outPut;
    }
    private void initQuestions(){
        for (SysQuestion question :sysQuestions ) {
            if(questions.containsKey(question.getDomain())){
                HashMap<Integer, List<SysQuestion>> levels=questions.get(question.getDomain());
                if(levels.containsKey(question.getLevel())){
                    List<SysQuestion> level=levels.get(question.getLevel());
                    level.add(level.size(),question);
                }else{
                    List<SysQuestion> level=new ArrayList<>();
                    level.add(level.size(),question);
                    levels.put(question.getLevel(),level);
                    questions.put(question.getDomain(),levels);
                }

            }else{
                HashMap<Integer, List<SysQuestion>> levels=new HashMap<>();
                List<SysQuestion> level=new ArrayList<>();
                level.add(level.size(),question);
                levels.put(question.getLevel(),level);
                questions.put(question.getDomain(),levels);
            }
        }

    }
    private void initDiagnosisDetailMap(){

        for (SysDiagnosisDetail diagnosisDetail:sysDiagnosisDetails){
            diagnosisDetailMap.put(diagnosisDetail.getQuestionId(),diagnosisDetail);
        }
    }

    public void initRecordMap(){
        for (SysQuestionRecord record:records){
            recordMap.put(record.getQuestionId(),record);
        }
    }

    private HashMap<String,Double>getScoreForRaddar(String items_str, List<TreeSelect> domainTrees,HashMap<Long,Double>getScores_l3){
        items_str=items_str.substring(6,items_str.length()-1);
        items_str=items_str.replaceAll("；",";");
        List<String> items=new ArrayList<String>(Arrays.asList(items_str.split(";")));
        int target_level=Integer.parseInt(items.get(0));
        items.remove(0);
        HashMap<String,Double> scores=new HashMap<>();
        List<TreeSelect> roots=getTreeRoot(domainTrees,items,1,target_level);
        for(TreeSelect root:roots){
            Double score=getScoreForRoot(root,getScores_l3);
            scores.put(root.getLabel(),score);
        }
        return  scores;
    }
    private HashMap<String, HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>> getTableLabelsForReport( List<TreeSelect> domainTrees,HashMap<Long,Double>getScores_l3,HashMap<Long,HashMap<String,List<List<String>>>>getLabel_l3){
        HashMap<String, HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>>labels=new HashMap<>();
        for (TreeSelect level_1:domainTrees){
            HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>labels_1=new HashMap<>();
            String level_name_1=level_1.getLabel();
            for (TreeSelect level_2:level_1.getChildren()){
                HashMap<String, HashMap<String, List<List<String>>>> labels_2=new HashMap<>();
                String level_name_2=level_2.getLabel();
                if(level_2.getChildren()==null||level_2.getChildren().size()==0){
                    String level_name_3 = level_2.getLabel();
                    HashMap<String, List<List<String>>> label = getLabel_l3.get(level_2.getId());
                    labels_2.put(level_name_3,label);
                }else {
                    for (TreeSelect Level_3 : level_2.getChildren()) {
                        String level_name_3 = level_1.getLabel();
                        HashMap<String, List<List<String>>> label = getLabel_l3.get(Level_3.getId());
                        labels_2.put(level_name_3,label);
                    }
                }
                labels_1.put(level_name_2,labels_2);
            }
            labels.put(level_name_1,labels_1);
        }
        return labels;
    }

    private HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> getProblemLabelsForReport( List<TreeSelect> domainTrees,HashMap<Long,Double>getScores_l3,HashMap<Long,HashMap<String,String>>getLabel_l3){
        HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>>labels=new HashMap<>();
        for (TreeSelect level_1:domainTrees){
            HashMap<String, HashMap<String, HashMap<String, String>>>labels_1=new HashMap<>();
            String level_name_1=level_1.getLabel();
            for (TreeSelect level_2:level_1.getChildren()){
                HashMap<String, HashMap<String, String>> labels_2=new HashMap<>();
                String level_name_2=level_2.getLabel();
                if(level_2.getChildren()==null||level_2.getChildren().size()==0){
                    String level_name_3 = level_2.getLabel();
                    HashMap<String, String> label = getLabel_l3.get(level_2.getId());
                    if(label.containsKey("undone"))
                        labels_2.put(level_name_3,label);
                }else {
                    for (TreeSelect Level_3 : level_2.getChildren()) {
                        String level_name_3 = Level_3.getLabel();
                        HashMap<String, String> label = getLabel_l3.get(Level_3.getId());
                        if(label.containsKey("undone"))
                            labels_2.put(level_name_3,label);
                    }
                }
                if(labels_2.size()>0)
                    labels_1.put(level_name_2,labels_2);
            }
            if(labels_1.size()>0)
                labels.put(level_name_1,labels_1);
        }
        return labels;
    }
    private HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> getSuggestionLabelsForReport( List<TreeSelect> domainTrees,HashMap<Long,Double>getScores_l3,HashMap<Long,HashMap<String,String>>getLabel_l3){
        HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>>labels=new HashMap<>();
        for (TreeSelect level_1:domainTrees){
            HashMap<String, HashMap<String, HashMap<String, String>>>labels_1=new HashMap<>();
            String level_name_1=level_1.getLabel();
            for (TreeSelect level_2:level_1.getChildren()){
                HashMap<String, HashMap<String, String>> labels_2=new HashMap<>();
                String level_name_2=level_2.getLabel();
                if(level_2.getChildren()==null||level_2.getChildren().size()==0){
                    String level_name_3 = level_2.getLabel();
                    HashMap<String, String> label = getLabel_l3.get(level_2.getId());
                    if(label==null)
                        continue;
                    if(label.containsKey("suggestion"))
                        labels_2.put(level_name_3,label);
                }else {
                    for (TreeSelect Level_3 : level_2.getChildren()) {
                        String level_name_3 = Level_3.getLabel();
                        HashMap<String, String> label = getLabel_l3.get(Level_3.getId());
                        if(label==null)
                            continue;
                        if(label.containsKey("suggestion"))
                            labels_2.put(level_name_3,label);
                    }
                }
                if(labels_2.size()>0)
                    labels_1.put(level_name_2,labels_2);
            }
            if(labels_1.size()>0)
                labels.put(level_name_1,labels_1);
        }
        return labels;
    }


    private  Double getScoreForRoot(TreeSelect root,HashMap<Long,Double>getScores_l3){

        if(root.getChildren()!=null && root.getChildren().size()>0){
            Double score=0.0;
            for(TreeSelect croot:root.getChildren()){
                Double tscore=getScoreForRoot(croot,getScores_l3);
                System.out.println(croot.getLabel()+tscore);
                score+=tscore;
            }
            score=score/root.getChildren().size();
            return  Math.round(score * 10) * 0.1d;
        }else{
            return getScores_l3.get(root.getId());
        }


    }

    private   List<TreeSelect> getTreeRoot(List<TreeSelect> domainTrees,List<String> items,int current_level,int target_level){
        List<TreeSelect> roots=new ArrayList<>();
        if(current_level<target_level){
            current_level++;
            for(TreeSelect subDomainTree:domainTrees){
                List<TreeSelect> subroots=getTreeRoot(subDomainTree.getChildren(),items,current_level,target_level);
                roots.addAll(subroots);
            }
        }else{
            for(TreeSelect subDomainTree:domainTrees){
                if(items.contains(subDomainTree.getLabel()))
                    roots.add(subDomainTree) ;
            }
        }
        return roots;
    }

    private HashMap<Long,Double>getScores_l3(HashMap<Long, SysDiagnosisDetail> diagnosisDetailMap, HashMap<Long,HashMap<Integer, List<SysQuestion>>> questions ){
        HashMap<Long,Double> scores=new HashMap<>();
        for (Long dominId:questions.keySet()){
            HashMap<Integer, List<SysQuestion>> levels=questions.get(dominId);
            double score=0;
            for (Integer level_id:levels.keySet()){
                List<SysQuestion> level=levels.get(level_id);
                for(SysQuestion question:level){
                    if(diagnosisDetailMap.containsKey(question.getQuestionId()))
                        score+=diagnosisDetailMap.get(question.getQuestionId()).getScore();
                }
            }
            scores.put(dominId,score);
        }
        return  scores;
    }

    private HashMap<Long,HashMap<String,String>>getLabel_l3(HashMap<Long,SysDiagnosisDetail> diagnosisDetailMap, HashMap<Long,HashMap<Integer, List<SysQuestion>>> questions ){
        HashMap<Long,HashMap<String,String>> result=new HashMap<>();
        for (Long dominId:questions.keySet()){
            HashMap<Integer, List<SysQuestion>> levels=questions.get(dominId);
            List<String> perfect=new ArrayList<>();
            List<String> undone=new ArrayList<>();
            List<String> imperfect=new ArrayList<>();
            List<String> sugestion=new ArrayList<>();
            HashMap<String,String> items=new HashMap<>();

            for (Integer level_id:levels.keySet()){
                List<SysQuestion> level=levels.get(level_id);
                for(SysQuestion question:level){
                    double score=diagnosisDetailMap.get(question.getQuestionId()).getScore();
                    HashMap<String,String> qlabel=getLabelForReport(score,question);
                    if(qlabel.containsKey("perfect"))
                        perfect.add(qlabel.get("perfect"));
                    if(qlabel.containsKey("undone"))
                        undone.add(qlabel.get("undone"));
                    if(qlabel.containsKey("imperfect"))
                        imperfect.add(qlabel.get("imperfect"));
                    if(qlabel.containsKey("suggestion"))
                        sugestion.add(qlabel.get("suggestion"));
                }
            }
            if(perfect.size()>0){
                String label=String.join("；", perfect);
                if(!label.startsWith("企业")&& !label.startsWith("公司"))
                    label="企业"+label;
                items.put("perfect", label );;
            }
            if(undone.size()>0){
                String label=String.join("；", undone)+"。";
                if(!label.startsWith("企业")&& !label.startsWith("公司"))
                    label="企业"+label;
                items.put("undone","不足之处："+ label );;
            }
            if(imperfect.size()>0){
                String label=String.join("；", imperfect)+"。";
                if(!label.startsWith("企业")&& !label.startsWith("公司"))
                    label="企业"+label;
                items.put("imperfect", label );;
            }
            if(undone.size()>0){
                String label=String.join("；", undone)+"。";
                if(!label.startsWith("企业")&& !label.startsWith("公司"))
                    label="企业"+label;
                items.put("undone","不足之处："+ label );;
            }
            if(sugestion.size()>0){
                String label=String.join("；", sugestion)+"。";
//                if(!label.startsWith("企业")&& !label.startsWith("公司"))
//                    label="企业"+label;
                items.put("suggestion", label );;
            }
            result.put(dominId,items);
        }
        return  result;
    }
    private HashMap<String,String> getLabelForReport(double score,SysQuestion question){
        HashMap<String,String> result=new HashMap<>(0);
        String label=question.getLabel().replaceAll("%3f", "").replaceAll("[?]", "").replaceAll("[？]", "").trim();
        if(label.indexOf("多选")!=-1){
            if(label.indexOf("(")!=-1){
                label=label.substring(0,label.lastIndexOf("("));
            }
            if(label.indexOf("（")!=-1){
                label=label.substring(0,label.lastIndexOf("（"));
            }
        }
        String detail=question.getDetail();
        JSONObject q= JSON.parseObject(detail);
        // {"label":" 企业优化岗位结构的情况（可多选）","tag":"el-checkbox-group","tagIcon":"checkbox","defaultValue":[],"span":24,"labelWidth":null,"style":{},"optionType":"default","border":false,"size":"medium","disabled":false,"required":false,"options":[{"label": "建立机制", "value": 0}, {"label": "基于评估进行优化", "value": 1}, {"label": "定期对岗位结构和职责适配度进行评估", "value": 2}],"regList":[],"changeTag":true,"document":"https://element.eleme.cn/#/zh-CN/component/checkbox","formId":102,"renderKey":16532597713888,"layout":"colFormItem","vModel":"field8","score":5,"sort":8,"domain":12,"level":3}
        //{"label":" 企业是否已明确智能制造责任部门？","tag":"el-radio-group","tagIcon":"radio","span":24,"labelWidth":null,"style":{},"optionType":"default","border":false,"size":"medium","disabled":false,"required":false,"options":[{"label": "是", "value": 0}, {"label": "否", "value": 1}],"regList":[],"changeTag":true,"document":"https://element.eleme.cn/#/zh-CN/component/radio","formId":101,"renderKey":16532594151835,"layout":"colFormItem","vModel":"field5","score":5,"sort":5,"domain":12,"level":2,"questionId":5}
        // {"label":" 企业持续优化战略的证明资料列表","tag":"el-upload","tagIcon":"upload","action":"/dev-api/common/upload","defaultValue":null,"labelWidth":null,"disabled":false,"required":false,"accept":".pdf","name":"file","auto-upload":true,"showTip":true,"buttonText":"点击上传","fileSize":20,"sizeUnit":"MB","list-type":"text","multiple":true,"regList":[],"changeTag":true,"document":"https://element.eleme.cn/#/zh-CN/component/upload","formId":101,"span":24,"renderKey":1653556454553,"layout":"colFormItem","vModel":"field101","score":5,"sort":9,"domain":12,"level":"3","questionId":154}
        if("radio".equals(q.get("tagIcon"))){
            if (score==question.getScore()){
                label=label.replaceAll("是否已","已经").replaceAll("是否","已经");
                result.put("perfect",label);
            }else if(score==0){
                String sugestion=label;
                sugestion="建议"+sugestion.replaceAll("是否已","").replaceAll("是否","");
                result.put("suggestion",sugestion);
                label=label.replaceAll("是否已","尚未").replaceAll("是否","尚未");
                result.put("undone",label);


            }else{
                label=label.replaceAll("是否已","部分完成").replaceAll("是否","部分完成");
                result.put("imperfect",label);
            }

        }else if("checkbox".equals(q.get("tagIcon"))){

            String select="<xl>";
            JSONArray options=q.getJSONArray("options");
            List<String> items=new ArrayList<>();
            for(Object option :options){
                JSONObject optionj=(JSONObject)option;
                items.add(optionj.getString("label"));
            }
            select+=String.join("、", items);

            if (score==question.getScore()){
                label=label.replaceAll("是否已","已经").replaceAll("是否","已经").replaceAll("哪些","")+":"+select+"<xl>";
                result.put("perfect",label);
            }else if(score==0){
                String sugestion=label;
                sugestion="建议"+sugestion.replaceAll("是否已","").replaceAll("是否","").replaceAll("哪些","")+":"+select+"<xl>";
                result.put("suggestion",sugestion);
                label=label.replaceAll("是否已","尚未").replaceAll("是否","尚未").replaceAll("哪些","")+":"+select+"<xl>";
                result.put("undone",label);
            }else{
                SysQuestionRecord qrecord=null;
                if(recordMap.containsKey(question.getQuestionId()))
                    qrecord=recordMap.get(question.getQuestionId());
                if(qrecord!=null){

                    String dselect="<xl>";
                    String udselect="<xl>";
                    List<String>ditems=new ArrayList<>();
                    List<String>uditems=new ArrayList<>();
                    JSONArray answer=JSONArray.parseArray(qrecord.getAnswer());
                    for(Object option :options){
                        JSONObject optionj=(JSONObject)option;
                        int value=optionj.getInteger("value");
                        if(answer.contains(value)){
                            ditems.add(optionj.getString("label"));
                        }else{
                            uditems.add(optionj.getString("label"));
                        }

                    }

                    if(ditems.size()>0){
                        dselect+=String.join("、",ditems);
                        String dlabel=label.replaceAll("是否已","").replaceAll("是否","").replaceAll("哪些","")+":"+dselect+"<xl>";
                        result.put("perfect",dlabel);
                    }
                    if(uditems.size()>0){
                        String sugestion=label;
                        udselect+=String.join("、",uditems);
                        String ndlabel=label.replaceAll("是否已","").replaceAll("是否","").replaceAll("哪些","")+":"+udselect+"<xl>";
                        result.put("undone",ndlabel);

                        sugestion="建议"+sugestion.replaceAll("是否已","").replaceAll("是否","").replaceAll("哪些","")+":"+udselect+"<xl>";
                        result.put("suggestion",sugestion);
                    }





                }
            }

        }else if("upload".equals(q.get("tagIcon"))){


        }else{
            if (score==question.getScore()){
                label=label.replaceAll("是否已","已经").replaceAll("是否","已经");
                result.put("perfect",label);
            }else if(score==0){
                String sugestion=label;
                sugestion="建议"+sugestion.replaceAll("是否已","").replaceAll("是否","");
                result.put("suggestion",sugestion);
                label=label.replaceAll("是否已","尚未").replaceAll("是否","尚未");
                result.put("undone",label);
            }else{
                label=label.replaceAll("是否已","部分完成").replaceAll("是否","部分完成");
                result.put("imperfect",label);
            }
            return result;
        }
        return result;
    }

    private String getQuestionLevelLabel(int index){
        switch (index){
            case 0:
                return "";
            case 1:
                return "一级";
            case 2:
                return "二级";
            case 3:
                return "三级";
            default:

                return "";
        }

    }


    public String getOutPut() {
        return outPut;
    }

    public void setOutPut(String outPut) {
        this.outPut = outPut;
    }

    public String getLocalPath() {
        return localPath;
    }

    public void setLocalPath(String localPath) {
        this.localPath = localPath;
    }

    public String getReporttmpl() {
        return reporttmpl;
    }

    public void setReporttmpl(String reporttmpl) {
        this.reporttmpl = reporttmpl;
    }

    public XWPFDocument getDoc() {
        return doc;
    }

    public void setDoc(XWPFDocument doc) {
        this.doc = doc;
    }

    public Long getCompanyId() {
        return companyId;
    }

    public void setCompanyId(Long companyId) {
        this.companyId = companyId;
    }

    public Long getNaireId() {
        return naireId;
    }

    public void setNaireId(Long naireId) {
        this.naireId = naireId;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public List<TreeSelect> getDomainTrees() {
        return domainTrees;
    }

    public void setDomainTrees(List<TreeSelect> domainTrees) {
        this.domainTrees = domainTrees;
    }

    public HashMap<Long, Double> getGetScores_l3() {
        return getScores_l3;
    }

    public void setGetScores_l3(HashMap<Long, Double> getScores_l3) {
        this.getScores_l3 = getScores_l3;
    }

    public HashMap<Long, HashMap<String, String>> getLabels() {
        return labels;
    }

    public void setLabels(HashMap<Long, HashMap<String, String>> labels) {
        this.labels = labels;
    }
}
